package mqttlib

import (
	"MqttCloudProtocolServer/publiclib/datamodel"
	"MqttCloudProtocolServer/publiclib/datamodel/dborm"
	"sync"
	"time"

	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/wonderivan/logger"
)

//MqttCSPareClass MQTT收发成对打包
//待优化：RegisterEvent注册连接与接收订阅的处理事项，断连接与重连无需处理。将MQTT连接客户端合并成一个
type MqttCSPareClass struct {
	OperatorBase
	//clientData   *datamodel.MqttClient
	clientdbData *dborm.Mqttconf
	receiver     func(key string, buffer []uint8)
	topicPub     string
	topicSub     string
	clientObj    mqtt.Client
	retained     bool
	syncObj      sync.RWMutex
}

//InitTopic Fun
func (_this *MqttCSPareClass) InitTopic( /*totTopic string*/ ) bool {
	_this.topicPub = _this.clientdbData.PubTopic
	_this.topicSub = _this.clientdbData.SubTopic
	_this.retained = _this.clientdbData.Retained != 0
	/*if _this.clientdbData.UseTopicTip {
		_this.topicPub = totTopic + "-" + _this.topicPub
		_this.topicSub = totTopic + "-" + _this.topicSub
	}
	if _this.clientdbData.AutoAddMachineName {
		_this.topicPub = _this.key + "-" + _this.topicPub
		_this.topicSub = _this.key + "-" + _this.topicSub
	}*/
	return true
}

//SubMessage 订阅消息
func (_this *MqttCSPareClass) SubMessage() {
	logger.Debug("sub:" + _this.topicSub)

	_this.syncObj.Lock()
	if token := _this.clientObj.Subscribe(_this.topicSub, 0, _this.getMessageHandler); token.Error() != nil {
		logger.Alert("token.Error()")
		logger.Alert(token.Error().Error())
		token.Wait()
		//os.Exit(1)
	}
	_this.syncObj.Unlock()
}

func (_this *MqttCSPareClass) getMessageHandler(client mqtt.Client, message mqtt.Message) {
	//logger.Info("??")
	//logger.Info("receive" + string(message.Payload()))
	//_this.SendData(message.Payload())
	if _this.receiver != nil {
		//logger.Trace("subframe:" + helplib.BufferToString(message.Payload()))
		_this.receiver(_this.GetKey(), message.Payload())
		//logger.Info("receive" + string(message.Payload()))
		//_this.SendData(message.Payload())
	}
}

//Start 启动函数。不太具备实际意义了
func (_this *MqttCSPareClass) Start() bool {
	return _this.clientdbData == nil
}

//Modify Fun
func (_this *MqttCSPareClass) Modify(params interface{}) bool {
	switch params.(type) {
	case *datamodel.MqttClient:
		//_this.clientData = params.(*datamodel.MqttClient)
		break
	case *dborm.Mqttconf:
		_this.clientdbData = params.(*dborm.Mqttconf)
		break
	default:
		return false
	}
	return true
}

//Close Fun 仅取消订阅
func (_this *MqttCSPareClass) Close() bool {
	_this.syncObj.Lock()
	if _this.clientObj != nil && _this.clientObj.IsConnected() {
		if token := _this.clientObj.Unsubscribe(_this.topicSub); token.WaitTimeout(time.Second*5) && token.Error() != nil {
			logger.Alert(token.Error())
		}
	}
	_this.syncObj.Unlock()
	return true
}

//SendData Fun
func (_this *MqttCSPareClass) SendData(buffer []uint8) bool {
	_this.syncObj.RLock()
	defer _this.syncObj.RUnlock()
	if _this.clientObj != nil && _this.clientObj.IsConnected() {
		connected := _this.clientObj.IsConnected()
		if _this.clientObj != nil && connected {
			//logger.Debug("pub:" + _this.topicPub)
			//logger.Debug("pubframe:" + helplib.BufferToString(buffer))
			_this.clientObj.Publish(_this.topicPub, 0, _this.retained, buffer)
			return true
		}
		logger.Alert("pub error")
	} else if _this.clientObj == nil {
		logger.Info("MQTT接受，MQTT对象尚未初始化")

	} else if !_this.clientObj.IsConnected() {
		logger.Info("MQTT接受，MQTT对象尚未连接")
	}
	return false
}

//SetReceive Fun
func (_this *MqttCSPareClass) SetReceive(callback func(key string, buffer []uint8)) {
	_this.receiver = callback
}

//GetTopicSub 获取Topic
func (_this *MqttCSPareClass) GetTopicSub() string {
	return _this.topicSub
}

//GetTopicPub 获取Topic
func (_this *MqttCSPareClass) GetTopicPub() string {
	return _this.topicPub
}

//SetTopicTip 获取Topic
func (_this *MqttCSPareClass) SetTopicTip(topicPub, topicSub string) {
	_this.topicSub = topicSub
	_this.topicPub = topicPub
}

//SetMqttClient 当mqttClient发生改变时，需要通知回来
func (_this *MqttCSPareClass) SetMqttClient(client mqtt.Client) {
	_this.syncObj.Lock()
	_this.clientObj = client
	_this.syncObj.Unlock()
}
